package com.lzhsite.technology.deepcopy;
//背景：

//对象o可能有很多字段，有的字段上面有个EnableAES的annotation；在调用crypt方法之后，会对这些字段进行
//加密。在intercept 方法中，先调用crypt进行加密，然后再调用invocation.proceed入库。
//
//待优化：
//这样做有个副作用，invocation里面的原始输入数据可能会被加密，和原来不一样。
//
//有什么版本可以在入库前按需加密，但是又不影响原始数据
//注意深度拷贝对象是非常消耗cpu的。
//
//答案我还没提交git，所以别指望从git上走捷径。

import java.beans.PropertyDescriptor;
import java.util.List;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.Invocation;

import com.lzhsite.core.utils.cryptors.AESCryptor;

public class TestDeepCopy {

	private void crypt(Object o) throws Exception {
		Class clz = o.getClass();
		if (clz.isPrimitive()) {
			return;
		}
		// 找出属于某个bean需要加密的字段列表
		List<PropertyDescriptor> pds = getPropertyDescriptors(clz);

		for (PropertyDescriptor pd : pds) {
			String origin = (String) pd.getReadMethod().invoke(o);
			pd.getWriteMethod().invoke(o, (Object) AESCryptor.getInstance().encrypt(origin));
		}
		return;
	}

	private List<PropertyDescriptor> getPropertyDescriptors(Class clz) {
		// TODO Auto-generated method stub
		return null;
	}

	public Object intercept(Invocation invocation) throws Exception {
		if (invocation.getTarget() instanceof ParameterHandler) {
			ParameterHandler ph = (ParameterHandler) invocation.getTarget();
			Object param = ph.getParameterObject();
			if (param == null) {
				return invocation.proceed();
			}
			if (param instanceof List) {
				List list = (List) param;
				list.forEach(o -> {
					try {
						crypt(o);
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				});
			} else {
				crypt(param);
			}
			return invocation.proceed(); // 这里执行入库操作
		}
		// 其他先不管
		return null;
	}

}
